package cn.wolfcode.mq.listener;

import cn.wolfcode.common.domain.UserInfo;
import cn.wolfcode.common.exception.BusinessException;
import cn.wolfcode.common.web.Result;
import cn.wolfcode.domain.SeckillProductVo;
import cn.wolfcode.mq.MQConstant;
import cn.wolfcode.mq.OrderMQResult;
import cn.wolfcode.mq.OrderMessage;
import cn.wolfcode.mq.OrderTimeOutMessage;
import cn.wolfcode.service.IOrderInfoService;
import cn.wolfcode.service.ISeckillProductService;
import cn.wolfcode.web.msg.SeckillCodeMsg;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;

/**
 * @author BAI
 */

@RocketMQMessageListener(
        consumerGroup = MQConstant.ORDER_PENDING_CONSUMER_GROUP,
        topic = MQConstant.ORDER_PENDING_TOPIC
)
@Component
@Slf4j
public class OrderPendingMQMessageListener implements RocketMQListener<OrderMessage> {
    private final IOrderInfoService orderInfoService;

    private final ISeckillProductService seckillProductService;

    private final RocketMQTemplate rocketMQTemplate;

    public OrderPendingMQMessageListener(IOrderInfoService orderInfoService, ISeckillProductService seckillProductService, RocketMQTemplate rocketMQTemplate) {
        this.orderInfoService = orderInfoService;
        this.seckillProductService = seckillProductService;
        this.rocketMQTemplate = rocketMQTemplate;
    }

    @Override
    public void onMessage(OrderMessage orderMessage) {
        OrderMQResult orderMQResult = new OrderMQResult();

        orderMQResult.setSeckillId(orderMessage.getSeckillId());
        orderMQResult.setTime(orderMessage.getTime());
        orderMQResult.setMsg("秒杀成功");
        orderMQResult.setToken(orderMessage.getToken());
        orderMQResult.setCode(200);
        String orderNo="";

        try {
            // 查询秒杀商品
            SeckillProductVo seckillProductVo = seckillProductService.selectByIdAndTime(orderMessage.getSeckillId(), orderMessage.getTime());
            // 获取下单用户
            UserInfo user = new UserInfo();
            user.setPhone(orderMessage.getUserPhone());
            // 创建订单
            orderNo   = orderInfoService.doSeckill(user, seckillProductVo);
            orderMQResult.setOrderNo(orderNo);

        } catch (BusinessException businessException) {
            log.error("[业务异常]秒杀失败,失败原因:{}", businessException.getCodeMsg());
            orderMQResult.setMsg(businessException.getCodeMsg().getMsg());
            orderMQResult.setCode(businessException.getCodeMsg().getCode());
        } catch (Exception e) {
            log.error("[系统异常]秒杀失败,失败原因:{}", e.getMessage());
            // 同时 Redis 令牌需要回滚,库存需要回滚

            orderMQResult.setMsg(SeckillCodeMsg.SECKILL_ERROR.getMsg());
            orderMQResult.setCode(SeckillCodeMsg.SECKILL_ERROR.getCode());
            // 防止消费者重试
            // throw e;
        }

        // 发送订单创建成结果
        SendResult sendResult = rocketMQTemplate.syncSend(MQConstant.ORDER_RESULT_TOPIC, orderMQResult);
        log.info("[秒杀成功] 发送订单创建结果:{}", JSON.toJSONString(orderMQResult));

        if (orderMQResult.getCode() != Result.SUCCESS_CODE) {
            // 同时 Redis 令牌需要回滚,库存需要回滚 ,本地标识需要回滚
            orderInfoService.rollbackOrderSeckill(orderMessage.getSeckillId(), orderMessage.getTime(), orderMessage.getUserPhone());
        }else {
            // 发送延迟消息,用于检查订单是否支付
            OrderTimeOutMessage orderTimeOutMessage = new OrderTimeOutMessage(orderMessage.getTime(), orderMessage.getSeckillId(), orderMessage.getUserPhone(), orderNo);
            Message<OrderTimeOutMessage> build = MessageBuilder.withPayload(orderTimeOutMessage).build();
            // 1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h
            rocketMQTemplate.syncSend(MQConstant.ORDER_PAY_TIMEOUT_TOPIC,build,2000,MQConstant.ORDER_PAY_TIMEOUT_DELAY_LEVEL);
        }

    }
}
